/*
    虚拟机相关类的实现：虚拟机类、虚拟机管理类
    1. 虚拟机类：服务端资源的载体，将交换机管理模块、消息队列管理模块、绑定关系管理模块、消息管理模块进行融合
        属性：交换机管理模块句柄、消息队列管理模块句柄、绑定信息管理模块句柄、消息管理模块句柄
        方法：声明/删除交换机、声明/删除消息队列、绑定/解除绑定关系、获取指定交换机的所有绑定关系、向指定队列发布/消费/应答消息
    2. 虚拟机管理类：对虚拟机对象进行管理
*/
#pragma once
#include "exchanger.hpp"
#include "msg_queue.hpp"
#include "binding.hpp"
#include "message.hpp"

namespace mq
{
    class VirtualHost
    {
    public:
        using VirtualHostPtr = std::shared_ptr<VirtualHost>;

    public:
        VirtualHost(const std::string &name, const std::string &db_file, const std::string &durable_msg_file_dir): 
            _name(name),
            _exchanger_manager_ptr(std::make_shared<ExchangerManager>(db_file)),
            _msg_queue_manager_ptr(std::make_shared<MsgQueueManager>(db_file)),
            _binding_manager_ptr(std::make_shared<BindingManager>(db_file)),
            _msg_manager_ptr(std::make_shared<MessageManager>(durable_msg_file_dir))
        {
            /*
                交换机、消息队列、绑定关系在创建对象的时候就已经完成了数据的恢复，而消息需要手动恢复
            */
            MsgQueueManager::MsgQueueMap msg_queue_map = _msg_queue_manager_ptr->getAllMsgQueues();
            for (auto &e : msg_queue_map)
            {
                _msg_manager_ptr->initQueueMessage(e.first);
            }

        }

        // 声明交换机
        bool declareExchanger(const std::string &name, ExchangerType type, bool durable, bool auto_delete, const google::protobuf::Map<std::string, std::string> &args)
        {
            return _exchanger_manager_ptr->declareExchanger(name, type, durable, auto_delete, args);
        }

        // 删除交换机
        void removeExchanger(const std::string &name)
        {
            // 1. 删除交换机
            _exchanger_manager_ptr->removeExchanger(name);

            // 2. 删除交换机绑定关系
            _binding_manager_ptr->removeExchangerBindings(name);
        }

        // 获取指定交换机
        Exchanger::ExchangerPtr getExchanger(const std::string &name)
        {
            return _exchanger_manager_ptr->getExchanger(name);
        }

        // 声明消息队列
        bool declareMsgQueue(const std::string &name, bool durable, bool exclusive, bool auto_delete, const google::protobuf::Map<std::string, std::string>& args)
        {
            // 1. 初始化队列消息管理对象
            _msg_manager_ptr->initQueueMessage(name);

            // 2. 声明消息队列
            return _msg_queue_manager_ptr->declareMsgQueue(name, durable, exclusive, auto_delete, args);
        }

        // 删除消息队列
        void removeMsgQueue(const std::string &name)
        {
            // 1. 删除队列消息管理对象
            _msg_manager_ptr->destroyQueueMessage(name);

            // 2. 删除消息队列
            _msg_queue_manager_ptr->removeMsgQueue(name);

            // 3. 删除队列绑定关系
            _binding_manager_ptr->removeMsgQueueBindings(name);
        }

        // 绑定绑定关系
        bool bind(const std::string &exchanger_name, const std::string &msg_queue_name, const std::string &routing_key)
        {
            // 判断交换机和消息队列是否存在
            Exchanger::ExchangerPtr exchanger_ptr = _exchanger_manager_ptr->getExchanger(exchanger_name);
            MsgQueue::MsgQueuePtr msg_queue_ptr = _msg_queue_manager_ptr->getMsgQueue(msg_queue_name);
            if (exchanger_ptr && msg_queue_ptr) // 绑定关系的持久化取决于交换机和消息队列是否持久化
            {
                return _binding_manager_ptr->bind(exchanger_name, msg_queue_name, routing_key, exchanger_ptr->_durable && msg_queue_ptr->_durable);
            }
            else
            {
                DBG_LOG("exchanger or msg_queue not exist\n");
                return false;
            }
        }

        // 解除绑定关系
        void unbind(const std::string &exchanger_name, const std::string &msg_queue_name)
        {
            _binding_manager_ptr->unbind(exchanger_name, msg_queue_name);
        }

        // 获取指定交换机的所有绑定关系
        BindingManager::MsgQueueBindingMap exchangerBindings(const std::string &exchanger_name)
        {
            return _binding_manager_ptr->getExchangerBindings(exchanger_name);
        }

        // 向指定队列发布消息
        bool publish(const std::string &queue_name, const BasicProperties *properties, const std::string &body)
        {
            // 判断消息队列是否存在
            MsgQueue::MsgQueuePtr msg_queue_ptr = _msg_queue_manager_ptr->getMsgQueue(queue_name);
            if (!msg_queue_ptr)
                return false;
            _msg_manager_ptr->insertMsg(queue_name, properties, body, msg_queue_ptr->_durable);
            return true;
        }

        // 从指定队列消费消息
        MessagePtr consume(const std::string &queue_name)
        {
            return _msg_manager_ptr->popFront(queue_name);
        }

        // 向指定队列应答消息
        void ack(const std::string &queue_name, const std::string &msg_id)
        {
            _msg_manager_ptr->ackMsg(queue_name, msg_id);
        }

    public:
        /*
            下面是测试相关接口
        */
        // 判断指定交换机是否存在
        bool hasExchanger(const std::string &name)
        {
            return _exchanger_manager_ptr->hasExchanger(name);
        }

        // 判断指定消息队列是否存在
        bool hasMsgQueue(const std::string &name)
        {
            return _msg_queue_manager_ptr->hasMsgQueue(name);
        }

        // 判断绑定消息是否存在
        bool hasBinding(const std::string &exchanger_name, const std::string &msg_queue_name)
        {
            return _binding_manager_ptr->hasBinding(exchanger_name, msg_queue_name);
        }

        // 获取应答消息数量
        size_t getWaittingAckCnt(const std::string &queue_name)
        {
            return _msg_manager_ptr->getWaittingAckCnt(queue_name);
        }

        // 清空虚拟机
        void clear()
        { 
            _exchanger_manager_ptr->clear();
            _binding_manager_ptr->clear();
            _msg_queue_manager_ptr->clear();
            _msg_manager_ptr->clear();
        }

    private:
        std::string _name;                                            // 虚拟机名称
        ExchangerManager::ExchangerManagerPtr _exchanger_manager_ptr; // 交换机管理句柄
        MsgQueueManager::MsgQueueManagerPtr _msg_queue_manager_ptr;   // 消息队列管理句柄
        BindingManager::BindingManagerPtr _binding_manager_ptr;       // 绑定管理句柄
        MessageManager::MessageManagerPtr _msg_manager_ptr;           // 消息管理句柄
    };
}